package com.leyou.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.leyou.client.item.ItemClient;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.pojo.Order;
import com.leyou.order.pojo.OrderDetail;
import com.leyou.order.pojo.OrderStatusEnum;
import com.leyou.order.utils.PayHelper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 支付业务
 */
@Service
@Slf4j
public class PayService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayHelper payHelper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ItemClient itemClient;

    public String getPayUrl(Long id) {
        String orderId = id.toString();

        //1.从redis数据库中获取该订单的支付链接
        String payUrl = redisTemplate.opsForValue().get(orderId);

        if(StringUtils.isNotEmpty(payUrl)){
            //3.如果有，直接返回支付链接给用户
            return payUrl;
        }

        //根据订单Id查询订单
        Order order = orderMapper.selectById(id);

        //2.如果没有，则调用微信后台获取支付链接，把支付链接保存到redis中（设置有效期）
        payUrl = payHelper.unifiedOrder(id,order.getActualFee());

        //把支付保存到redis中
        redisTemplate.opsForValue().set(orderId,payUrl,2, TimeUnit.HOURS);

        return payUrl;


    }

    @GlobalTransactional
    public void wxNotify(Map<String, String> paramMap) {
        log.info("【微信支付回调】开始！");
        //校验返回结果是否合法
        payHelper.checkResp(paramMap);
        //1.接收参数
        Long orderId = Long.valueOf((String)paramMap.get("out_trade_no"));//订单ID
        Long totalFee = Long.valueOf((String)paramMap.get("total_fee"));//支付金额

        //2.查询订单
        Order order = orderMapper.selectById(orderId);
        if(order==null){
            throw new LyException(500,"订单号不存在");
        }
        Map<Object, Object> map = new HashMap<>();
        //根据订单号获取订单库存
        if (order.getStatus().equals(OrderStatusEnum.PAY_OUT.value())){
            //如果有库存,还能支付,如果没有,订单状态关闭
            OrderDetail entityDetail = new OrderDetail();
            entityDetail.setOrderId(orderId);
            QueryWrapper<OrderDetail> wrapper = Wrappers.query(entityDetail);
            //根据订单号查出所有的订单详情
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(orderDetails)){
                throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
            }
            //当前订单的商品数量与库存判断 id 库存数量
            //根据订单查出该订单下所有的商品id和库存
            Map<Long, Integer> skuMap = orderDetailMapper.findStockAndSkuId(orderId);
            orderDetails.forEach(orderDetail -> {
                skuMap.entrySet().forEach(sku->{
                    //id
                    Long skuId = sku.getKey();
                    //数量
                    Integer num = sku.getValue();
                    //判断
                    if (orderDetail.getSkuId().equals(skuId)){
                        if (orderDetail.getNum()<num){

                            log.info("库存不足,放弃吧");
                            throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH_ERROR);
                        }
                    }
                });
                //存shuId,num数量
                map.put(orderDetail.getSkuId(),orderDetail.getNum());
            });
        }

        //3.校验支付金额是否一致的
        if(order.getActualFee()!=totalFee){
            throw new LyException(500,"订单金额不一致");
        }

        try {
            //4.更新订单状态和时间
            order.setStatus(OrderStatusEnum.PAY_UP.value());
            order.setPayTime(new Date());
            orderMapper.updateById(order);

            log.info("【支付状态回调】更功新订单状态成");
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(500,"订单修改失败");
        }

    }
    /**
     * 查询订单状态 id:订单的编号
     */
    public Integer checkState(Long id) {
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }
    //用户下单后,超过20分钟不支付,归还商品库存,但订单状态为支付过期
    @GlobalTransactional
    public void outTimeOreder(Date date) {
        //获取数据库下单时间超过20分钟以上的订单ids
        List<Long> ids = orderMapper.findOrderIds(date, 1);

        if (CollectionUtils.isEmpty(ids)){
            return;
        }
        //skuId和商品数量
        Map<Long, Integer> map = new HashMap<>();
        //修改库存和订单状态
        ids.forEach(id->{
            Order order = new Order();
            //支付状态过期
            order.setStatus(OrderStatusEnum.PAY_OUT.value());
            order.setOrderId(id);
            orderMapper.updateById(order);
            //根据id获取订单详情
            OrderDetail entityOrder = new OrderDetail();
            entityOrder.setOrderId(id);
            QueryWrapper<OrderDetail> queryWrapper = Wrappers.query(entityOrder);

            //根据订单id获取详情
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(queryWrapper);
            orderDetails.forEach(orderDetail -> {
                map.put(orderDetail.getSkuId(),orderDetail.getNum());
            });
        });
        //获取每个订单的skuId和数量,加库存
        itemClient.plusStock(map);
    }
        //用户下单后,超过2小时支付成功的地方订单,状态改为已失效
    public void OutTwoTimeOrder(Date twoHourDate) {
        //抽取方法
          List<Long> ids= orderMapper.findOrderIds(twoHourDate,7);
        if (CollectionUtils.isEmpty(ids)){
            return;
        }
        //修改状态
        ids.forEach(id->{
            Order order = new Order();
            order.setStatus(OrderStatusEnum.CLOSED.value());
            order.setOrderId(id);
            //设置关闭时间
            order.setCloseTime(new Date());
            //更新状态和关闭时间
            orderMapper.updateById(order);
        });
    }
}
